/* Gauge - Performance Measurement Framework for Mobile Platforms
 * Copyright (C) 2013, Juha Hytonen <juha.a.hytonen@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.gauge.Probes;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.gauge.Measurement;
import org.gauge.Probe;

/**
 * Base class for probes accessing information in the proc filesystem. 
 */
public abstract class AbstractProcProbe implements Probe {

	private static Pattern valuePattern = Pattern.compile("\\s?\\d+\\s");

	@Override
	public Measurement GetMeasurement() throws Exception {
		String fileName = getFileNameToReadFrom();
		String lineCaption = getLineCaption();
		int valueIndex = getValueIndex();
		
		String line = readLineFrom(fileName, lineCaption);
		String valueString = extractValueFrom(line, valueIndex);
		int value = Integer.parseInt(valueString);
		Measurement measurement = new Measurement((Probe)this, value, getMeasurementUnit());
		return measurement;
	}

	protected String getFileNameToReadFrom() {
		return "";
	}

	protected String getLineCaption() {
		return "";
	}

	protected int getValueIndex() {
		return 0;
	}
	
	protected String getMeasurementUnit() {
		return "";
	}
	
	protected String readLineFrom(String fileName, String lineName) throws Exception {
		try {
			RandomAccessFile file = new RandomAccessFile(fileName, "r");
			String line = "";
			if (lineName.isEmpty()) { // Take first line.
				line = file.readLine();
			}
			else {
				line = findLineFrom(file, lineName);
			}
			file.close();
			return line;
		}
		catch(IOException e) {
			throw new Exception("Could not read meminfo");
		}
	}
	
	protected String findLineFrom(RandomAccessFile file, String lineName) throws Exception {
		String line = "";
		boolean correctLine = false;
		while (!correctLine) {
			line = file.readLine();
			Pattern namePattern = Pattern.compile(lineName); // e.g. MemTotal
			Matcher nameMatcher = namePattern.matcher(line);
			correctLine = nameMatcher.find();
		}
		
        if(correctLine) {
        	return line;
        }
        else {
			throw new Exception("Could not find " + lineName + " from file");
        }
	}
	
	protected String extractValueFrom(String line, int valueIndex) throws Exception {
		Matcher valueMatcher = valuePattern.matcher(line);
		scrollToValue(valueMatcher, valueIndex);
		if(valueMatcher.find()) {
			String value = line.substring(valueMatcher.start(), valueMatcher.end());
			return value.trim();
		}
		else {
			throw new Exception("Could not find a valid value");
		}
	}
	
	private void scrollToValue(Matcher valueMatcher, int valueIndex) throws Exception {
		for(int i = 0; i < valueIndex; i++) {
			if (!valueMatcher.find()) {
				throw new Exception("Could not find a valid value at given index");
			}
		}
	}

}
